﻿using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Model;
using LightCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using LightCAD.MathLib;
using LightCAD.Drawing;

namespace QdWater
{
    public class PipeAttribute : CptAttribute
    {
        public PipeAttribute(string category, string subCategorys) : base(category, subCategorys)
        {

        }
        static PipeAttribute()
        {
            CptTypeParamsDef<LcPipeDef>.ParamsDef = new ParameterSetDefinition { new ParameterDefinition { DataType = LcDataType.String, Name = "MaterialUuid", DisplayName = "材质" } };
        }
        public const string CommonWallUuid = "2C9EFB1F-88A6-0C29-93E1-9202689A7E13";
        public override LcComponentDefinition GetBuiltinCpt(string subCategory)
        {
            var typeParams = new LcParameterSet(CptTypeParamsDef<LcPipeDef>.ParamsDef);
            switch (subCategory)
            {
                case "水管":
                    //常规墙上的材质无意义
                    return new LcPipeDef(CommonWallUuid, "内置", subCategory, typeParams);
            }
            return null;
        }
    }
    [PipeAttribute("水管", "水管")]
    public class LcPipeDef : LcComponentDefinition
    {
        public LcPipeDef(string uuid, string name, string subCategory, LcParameterSet typeParams) : base(uuid, name, "水管", subCategory, typeParams)
        {
            this.Parameters = new ParameterSetDefinition
            {
                new ParameterDefinition(){ Name = "Width",DisplayName="管径", DataType=LcDataType.Double },
                new ParameterDefinition(){ Name = "Bottom",DisplayName="底高度", DataType=LcDataType.Double },
            };

            var mat = MaterialManager.DefaultMat;
            this.Solid3dProvider = new Solid3dProvider(name) { AssignMaterialsFunc = (c, s) => new LcMaterial[] { mat } };
        }
    }

    internal class LcPipe : DirectComponent, IWaterObject
    {
        public double Width { get; set; }
        public double Bottom { get; set; }

        public LcPipe(LcPipeDef wallDef) : base(wallDef)
        {
            this.Type = WaterElementType.Pipe;
            this.Curves = new Curve2dGroupCollection();
        }
        public Dictionary<long, LcElement> LinkElement { get; set; } = new Dictionary<long, LcElement> { };
        public SortedDictionary<int, WaterConnector> Connectors { get; set; } = new SortedDictionary<int, WaterConnector>();
        public List<Line2d> Outline { get; set; } = new List<Line2d>();
        WaterObjectType IWaterObject.WaterType { get { return WaterObjectType.PipeFitting; } }

        public List<Line2d> GetBaseLines()
        {
            List<Line2d> line2Ds = new List<Line2d>();
            for (int i = 0; i < this.Connectors.Count - 1; i += 2)
            {
                var start = this.Connectors.Values.ToList()[i].CenterPoint;
                var end = this.Connectors.Values.ToList()[i+1].CenterPoint;
                Line2d line2D = new Line2d(start, end);
                line2Ds.Add(line2D);
            }
            return line2Ds;
        }
        public override LcElement Clone()
        {
            var clone = Document.CreateObject<LcPipe>();
            clone.Copy(this);
            clone.Initilize(this.Document);
            return clone;

        }

        public override void Copy(LcElement src)
        {
            base.Copy(src);
            var wall = ((LcPipe)src);
        }

        public void Set(Vector2 start = null, Vector2 end = null, bool fireChangedEvent = true)
        {

        }

        protected override void OnPropertyChanged(string propertyName, LcPropertyGroup extPropGroup, LcProperty extProp)
        {
            base.OnPropertyChanged(propertyName, extPropGroup, extProp);
        }
        public override Box2 GetBoundingBox()
        {
            Box2 box2 = new Box2();
            foreach (var line in this.GetBaseLines())
            {
                Box2 lineBox = new Box2();
                lineBox.SetFromPoints(line.Start, line.End);
                box2.Union(lineBox);
            }
            return box2;
        }
        public override Box2 GetBoundingBox(Matrix3 matrix)
        {
            Box2 box2 = new Box2();
            foreach (WaterConnector connector in this.Connectors.Values)
            {
                box2.SetFromPoints(matrix.MultiplyPoint(connector.CenterPoint));
            }
            return box2;
        }
        public override bool IntersectWithBox(Polygon2d testPoly, List<RefChildElement> intersectChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                //如果元素盒子，与多边形盒子不相交，那就可能不相交
                return false;
            }
            return false;
        }

        public override bool IncludedByBox(Polygon2d testPoly, List<RefChildElement> includedChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                return false;
            }
            return false;
        }

        public override void Translate(double dx, double dy)
        {


        }
        public override void Move(Vector2 startPoint, Vector2 endPoint)
        {

        }
        public override void Scale(Vector2 basePoint, double scaleFactor)
        {

        }
        public override void Scale(Vector2 basePoint, Vector2 scaleVector)
        {
        }
        public override void Rotate(Vector2 basePoint, double rotateAngle)
        {

        }
        public override void Mirror(Vector2 axisStart, Vector2 axisEnd)
        {

        }
        public override void WriteProperties(Utf8JsonWriter writer, JsonSerializerOptions soptions)
        {
            base.WriteProperties(writer, soptions);

            writer.WriteNumberProperty(nameof(Width), this.Width);


            if (this.Bottom != 0)
            {
                writer.WriteNumberProperty(nameof(Bottom), this.Bottom);
            }

        }
        public override void ReadProperties(ref JsonElement jele)
        {
            base.ReadProperties(ref jele);

            this.Width = jele.ReadDoubleProperty(nameof(Width));

            this.Bottom = jele.ReadDoubleProperty(nameof(Bottom));

        }
    }
}
